package com.example.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.domain.po.User;
import com.example.domain.qo.user.DeletedQo;
import com.example.domain.qo.user.EditDataQo;
import com.example.domain.qo.user.EditQo;
import com.example.domain.qo.user.ListQo;
import com.example.domain.qo.user.SaveQo;
import com.example.domain.vo.user.EditDataVo;
import com.example.domain.vo.user.ListVo;
import com.example.mapper.UserMapper;
import com.example.service.UserService;
import com.example.tools.Result.GlobalException;
import com.example.tools.Result.ResultStatus;
import com.example.tools.SnowflakeIdWorker;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author czx
 * @ClassName: UserServiceImpl
 * @Description: TODO
 * @date 2022/1/28
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    /**
     * ID生成器（雪花算法）
     */
    SnowflakeIdWorker idWorker = new SnowflakeIdWorker();

    /***
     * UserMapper
     */
    private final UserMapper userMapper;

    /**
     * @return void    返回类型
     * @Author: czx
     * @Date: 2022/1/28
     * @Title: doSave
     * @Description: TODO
     * @params [saveQo]
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,
            isolation = Isolation.DEFAULT,
            rollbackFor = Exception.class)
    public void doSave(SaveQo saveQo) {
        //复制数据
        User user = new User();
        BeanUtils.copyProperties(saveQo, user);
        //设置其他参数
        user.setUserId(idWorker.nextId())
                .setDeleted(User.DELETED_NO)
                .setCreateTime(LocalDateTime.now())
                .setUpdateTime(LocalDateTime.now());
        //保存数据库
        int row;
        try {
            row = userMapper.saveUser(user);
        } catch (DuplicateKeyException e) {
            throw new GlobalException(ResultStatus.PARAM_ERROR, "添加失败");
        }
        if (row == 0) {
            throw new GlobalException(ResultStatus.PARAM_ERROR, "添加失败");
        }
    }

    /**
     * @return void    返回类型
     * @Author: czx
     * @Date: 2022/1/28
     * @Title: doEdit
     * @Description: TODO
     * @params [editQo]
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,
            isolation = Isolation.DEFAULT,
            rollbackFor = Exception.class)
    public void doEdit(EditQo editQo) {
        //构造条件查收
        Wrapper<User> wq = Wrappers.<User>lambdaQuery()
                .eq(User::getUserId, editQo.getUserId())
                .eq(User::getDeleted, User.DELETED_NO);
        //复制值（将EditQo类型转化为User类型插入更新数据库）
        User user = new User();
        BeanUtils.copyProperties(editQo, user);
        //设置其他参数
        user.setUpdateTime(LocalDateTime.now());
        //更新数据
        int row = userMapper.update(user, wq);
        if (row == 0) {
            throw new GlobalException(ResultStatus.PARAM_ERROR, "更新失败");
        }
    }

    /**
     * @return com.example.domain.vo.user.ListVo    返回类型
     * @Author: czx
     * @Date: 2022/2/7
     * @Title: doList
     * @Description: TODO
     * @params [listQo]
     */
    @Override
    @Transactional(readOnly = true)
    public ListVo doList(ListQo listQo) {
        //获取参数
        Integer size = listQo.size();
        Integer start = listQo.start();

        //查询用户数据
        List<User> userList = userMapper.getUserForList(size, start);
        //查询记录条数
        Integer count = userMapper.getUserForCount();

        //将User类型转化为ListVo.Meta类型
        List<ListVo.Meta> users = userList.stream()
                .map(this::User2ListVoMeta)
                .collect(Collectors.toList());
        return new ListVo().setRecordList(users)
                .setRecordCount(count);
    }

    /**
     * @return ListVo.Meta    返回类型
     * @Title: User2ListVoMeta
     * @params user
     */
    private ListVo.Meta User2ListVoMeta(User user) {
        ListVo.Meta meta = new ListVo.Meta();
        BeanUtils.copyProperties(user, meta);
        return meta;
    }

    /**
     * @return com.example.domain.vo.user.EditDataVo    返回类型
     * @Author: czx
     * @Date: 2022/2/9
     * @Title: doEditData
     * @Description: TODO
     * @params [editDataQo]
     */
    @Override
    @Transactional(readOnly = true)
    public EditDataVo doEditData(EditDataQo editDataQo) {
        //获取参数
        Long userId = editDataQo.getUserId();
        //查询数据
        User user = userMapper.getUsers(userId);
        if (user == null) {
            throw new GlobalException(ResultStatus.DATA_ERROR, "用户不存在");
        }
        //将User类型转化为EditDataVo类型
        EditDataVo editDataVo = new EditDataVo();
        BeanUtils.copyProperties(user, editDataVo);
        return editDataVo;
    }

    /**
     * @return void    返回类型
     * @Author: czx
     * @Date: 2022/2/9
     * @Title: doDelete
     * @Description: TODO
     * @params [deleteQo]
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,
            isolation = Isolation.DEFAULT,
            rollbackFor = Exception.class)
    public void doDelete(DeletedQo deletedQo) {
        //获取参数
        Long userId = deletedQo.getUserId();
        //通过参数进行逻辑删除（deleted状态 0否，1是）
        int row = userMapper.doDeleteById(userId);
        if (row == 0) {
            throw new GlobalException(ResultStatus.FAILED, "删除失败");
        }
    }

}
